/* 该程序是一个线程安全计数器示例，它可以用于点对线程化程序中的引用进行计数
 * 锁定机制被隐藏在函数中，调用程序不必为使用互斥量而担心。变量count和countlock
 * 都具有static属性，因此，这两个变量只能从counter.c内部引用。
 * 
 * 根据POSIX线程库的模式，如果成功，该程序中的函数就返回0；否则返回一个非零的错误码。
 */

// pthread_mutex_lock函数会一直阻塞到互斥量可用为止，而pthread_mutex_trylock函数总是立即返回。
// pthread_mutex_unlock函数用于释放指定的互斥量

/* note: 如果该程序中的变量count没有互斥锁保护，则在线程化程序中会出现什么问题？
 * 答： 如果没有锁定，就可能会获得不正确的count值。因为在大多数机器中，变量的增量
 *     和减量都不是原子操作（增量通常由三步组成：将内存为止加载到CPU寄存器中，向寄存器加1，
 *     并将值存回内存中）。假设当进程的时间片到期时，线程正处于增量的过程中。当进程再次
 *     运行时，线程调度程序可能会选择另一个线程运行。如果新挑选的线程也尝试对count进行
 *     增量或减量，那么，当原始线程完成其操作时，变量的值就可能是不正确的。
 * */

#include <pthread.h>
static int count = 0;
static pthread_mutex_t countlock = PTHREAD_MUTEX_INITIALIZER;   // 初始化线程

/* 将计数器增量 */
int increment (void) {
    int error;
    // 对线程进行加锁
    if (error = pthread_mutex_lock(&countlock))
        return error;
    
    count++;
    // 对线程进行解锁
    return pthread_mutex_unlock(&countlock);
}

/* 将计数器减量 */
int decrement (void) {
    int error;
    // 对线程进行加锁
    if (error = pthread_mutex_lock(&countlock))
        return error;
    
    count--;
    // 对线程进行解锁
    return pthread_mutex_unlock(&countlock);
}

/* 获取计数器 */
int getcount (int *countp) {
    int error;
    if (error = pthread_mutex_lock(&countlock))
        return error;
    
    *countp = count;
    return pthread_mutex_unlock(&countlock);
}
